package com.quanquan.user.service;

import DTO.PageDTO;
import DTO.store.StoreDTO;
import DTO.store.StoreInfoDTO;
import com.quanquan.user.dto.ConsumptionAmountDTO;
import com.quanquan.user.dto.IdDTO;
import com.quanquan.user.entity.ConsumptionAmount;
import com.quanquan.user.entity.User;
import com.quanquan.user.repository.ConsumptionAmountRepository;
import com.quanquan.user.request.ConsumptionAmountRequestBody;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.core.internal.Function;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import utils.DateUtils;
import utils.StringUtil;
import utils.UUIDGenerator;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 功能描述:
 *
 * @ClassName: ConsumptionAmountService
 * @Author: xiaoqianh丶
 * @Date: 2019-05-09 11:36
 * @Version: V1.0
 */
@Service
public class ConsumptionAmountService {

    private final RestTemplate restTemplate;
    private final ConsumptionAmountRepository consumptionAmountRepository;
    private final UserService userService;

    @Autowired
    public ConsumptionAmountService(ConsumptionAmountRepository consumptionAmountRepository, RestTemplate restTemplate, UserService userService) {
        this.consumptionAmountRepository = consumptionAmountRepository;
        this.restTemplate = restTemplate;
        this.userService = userService;
    }


    public void createConsumptionAmount(ConsumptionAmountRequestBody requestBody){
        ConsumptionAmount consumptionAmount = new ConsumptionAmount();//通过映射关系来赋值 //TODO 断点看一下
        BeanUtils.copyProperties(requestBody, consumptionAmount);
        consumptionAmount.setId(UUIDGenerator.getUUID());
        consumptionAmount.setCreateTime(DateUtils.currentDate());
        consumptionAmountRepository.save(consumptionAmount);

    }

    /**
     * 查找小票集合
     *
     * @return
     */
    public PageDTO<ConsumptionAmountDTO> list(ConsumptionAmountRequestBody requestBody) {
        Integer page = null == requestBody.getPage() ? 0 : requestBody.getPage();
        Integer size = null == requestBody.getSize() ? 10 : requestBody.getSize();
        String to = requestBody.getToDate();
        String from = requestBody.getFromDate();
        String keyword = requestBody.getKeyword();
        String ticketNum = requestBody.getTicketNum();
        String phone = requestBody.getPhone();
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        Pageable pageable = PageRequest.of(page, size, sort);

        Page<ConsumptionAmount> paged = consumptionAmountRepository.findAll((Specification<ConsumptionAmount>) (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            if (StringUtil.isNotEmpty(keyword)) {
                IdDTO idDTO1 = new IdDTO();
                idDTO1.setKeyWord(keyword);
                StoreInfoDTO storeInfoDTO1 = restTemplate.postForObject("http://QUANQUAN-STORE/store/page_find_store", idDTO1, StoreInfoDTO.class);
                List<StoreDTO> stores = storeInfoDTO1.getStoreDTOS();
                if (stores.size() > 0) {
                    StoreDTO storeDTO = stores.get(0);
                    predicates.add(cb.equal(root.get("storeId").as(String.class), storeDTO.getId()));
                } else if (stores.size() <= 0) {
                    List<User> users = userService.findListByKeyword(keyword);
                    if (users.size() > 0) {
                        User user = users.get(0);
                        predicates.add(cb.equal(root.get("userId").as(String.class), user.getId()));
                    } else {
                        predicates.add(cb.like(root.get("phone").as(String.class), "%" + keyword + "%"));
                    }

                }

            }

            if (StringUtil.isNotEmpty(from)) {
                Date startOfDay = DateUtils.getStartOfDay(DateUtils.strToDate(from, DateUtils.DATE));

                predicates.add(cb.greaterThanOrEqualTo(root.get("consumeDay").as(Date.class), startOfDay));
            }
            if (StringUtil.isNotEmpty(to)) {
                Date endOfDay = DateUtils.getEndOfDay(DateUtils.strToDate(to, DateUtils.DATE));
                predicates.add(cb.lessThanOrEqualTo(root.get("consumeDay").as(Date.class), endOfDay));
            }

            if (StringUtil.isNotEmpty(ticketNum)) {
                predicates.add(cb.like(root.get("ticketNum").as(String.class), "%" + ticketNum + "%"));
            }

            return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        }, pageable);
        List<ConsumptionAmountDTO> consumptionAmountDTOS = new ArrayList<>();
        List<ConsumptionAmount> consumptionAmounts = paged.getContent();
        List<String> storeIds = consumptionAmounts.stream().filter(distinctByKey(ConsumptionAmount::getStoreId)).map(ConsumptionAmount::getStoreId).collect(Collectors.toList());

        StoreInfoDTO storeInfoDTO = getStoreInfoDTO(storeIds);
        List<StoreDTO> storeDTOS = storeInfoDTO.getStoreDTOS();
        for (ConsumptionAmount consumptionAmount : consumptionAmounts) {
            ConsumptionAmountDTO consumptionAmountDTO = new ConsumptionAmountDTO();
            BeanUtils.copyProperties(consumptionAmount, consumptionAmountDTO);
            consumptionAmountDTO.setConsumptionAmountId(consumptionAmount.getId());
            consumptionAmountDTOS.add(consumptionAmountDTO);
        }

        for (ConsumptionAmountDTO consumptionAmountDTO : consumptionAmountDTOS) {
            for (StoreDTO storeDTO : storeDTOS) {
                if (consumptionAmountDTO.getStoreId().equals(storeDTO.getId())) {
                    consumptionAmountDTO.setStoreName(storeDTO.getStoreName());
                    consumptionAmountDTO.setStoreCommercial(storeDTO.getStoreCommercial());
                }
            }
        }

        List<String> phones = consumptionAmounts.stream().filter(distinctByKey(ConsumptionAmount::getPhone)).map(ConsumptionAmount::getPhone).collect(Collectors.toList());

        List<User> users = userService.findUsersByPhone(phones);
        //将积分的关于用户的信息补上
        for (User user : users) {
            for (ConsumptionAmountDTO consumptionAmountDTO : consumptionAmountDTOS) {
                if ((user.getPhone()).equals(consumptionAmountDTO.getPhone())) {
                    consumptionAmountDTO.setPhone(user.getPhone());
                    consumptionAmountDTO.setMemberName(user.getMemberName());
                    consumptionAmountDTO.setMemberCardNum(user.getMemberCardNum());
                }
            }
        }

        PageDTO<ConsumptionAmountDTO> pageDTO = new PageDTO<>();
        pageDTO.setTotal(paged.getTotalElements());
        pageDTO.setList(consumptionAmountDTOS);
        pageDTO.setTotalPage(paged.getTotalPages());
        pageDTO.setPage(page);
        pageDTO.setPageSize(size);
        pageDTO.setFromDate(from);
        pageDTO.setTicketNum(ticketNum);
        pageDTO.setPhone(phone);
        pageDTO.setToDate(to);
        pageDTO.setKeyword(keyword);
        return pageDTO;
    }

    private static <T> java.util.function.Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }

    /**
     * 拿取商铺的信息
     *
     * @param storeIds
     * @return
     */
    private StoreInfoDTO getStoreInfoDTO(List<String> storeIds) {
        IdDTO idDTO = new IdDTO();
        idDTO.setForeignKeyIds(storeIds);

        return restTemplate.postForObject("http://QUANQUAN-STORE/store/query_by_id_list", idDTO, StoreInfoDTO.class);
    }

}
